home *** CD-ROM | disk | FTP | other *** search
/ Cream of the Crop 26 / Cream of the Crop 26.iso / doom / quake.zip / HIPGRAPL.ZIP / CLIENT.QC < prev    next >
Text File  |  1997-04-09  |  48KB  |  1,822 lines

  1.  
  2. // prototypes
  3. void () W_WeaponFrame;
  4. void() W_SetCurrentAmmo;
  5. void() player_pain;
  6. void() player_stand1;
  7. void (vector org) spawn_tfog;
  8. void (vector org, entity death_owner) spawn_tdeath;
  9.  
  10. float modelindex_eyes, modelindex_player, modelindex_hammer;
  11.  
  12.  
  13. /*
  14. =============================================================================
  15.  
  16.                 LEVEL CHANGING / INTERMISSION
  17.  
  18. =============================================================================
  19. */
  20.  
  21. float    intermission_running;
  22. float    intermission_exittime;
  23.  
  24. /*QUAKED info_intermission (1 0.5 0.5) (-16 -16 -16) (16 16 16)
  25. This is the camera point for the intermission.
  26. Use mangle instead of angle, so you can set pitch or roll as well as yaw.  'pitch roll yaw'
  27. */
  28. void() info_intermission =
  29. {
  30. };
  31.  
  32.  
  33.  
  34. void() SetChangeParms =
  35. {
  36.     if (self.health <= 0)
  37.     {
  38.         SetNewParms ();
  39.         return;
  40.     }
  41.  
  42. //JIM
  43. // remove items
  44.     self.items = self.items - (self.items &
  45.    (IT_KEY1 | IT_KEY2 | IT_INVISIBILITY | IT_INVULNERABILITY | IT_SUIT | IT_QUAD ) );
  46. //MED
  47.    self.items2 = self.items2 - (self.items2 &
  48.    (HIP_IT_WETSUIT | HIP_IT_EMPATHY_SHIELDS ) );
  49. //MED
  50.    self.gravity = 1.0;
  51.  
  52. // cap super health
  53.     if (self.health > 100)
  54.         self.health = 100;
  55.     if (self.health < 50)
  56.         self.health = 50;
  57.     parm1 = self.items;
  58.     parm2 = self.health;
  59.     parm3 = self.armorvalue;
  60.     if (self.ammo_shells < 25)
  61.         parm4 = 25;
  62.     else
  63.         parm4 = self.ammo_shells;
  64.     parm5 = self.ammo_nails;
  65.     parm6 = self.ammo_rockets;
  66.     parm7 = self.ammo_cells;
  67.     parm8 = self.weapon;
  68.     parm9 = self.armortype * 100;
  69. };
  70.  
  71. void() SetNewParms =
  72. {
  73.     parm1 = IT_SHOTGUN | IT_AXE;
  74.     parm2 = 100;
  75.     parm3 = 0;
  76.     parm4 = 25;
  77.     parm5 = 0;
  78.     parm6 = 0;
  79.     parm7 = 0;
  80.     parm8 = 1;
  81.     parm9 = 0;
  82. };
  83.  
  84. void() DecodeLevelParms =
  85. {
  86. //HIPNOTIC
  87.    if (world.model == "maps/start.bsp")
  88.       SetNewParms ();      // take away all stuff on starting new episode
  89.    if (world.model == "maps/hip1m1.bsp")
  90.       SetNewParms ();      // take away all stuff on starting new episode
  91.    if (world.model == "maps/hip2m1.bsp")
  92.       SetNewParms ();      // take away all stuff on starting new episode
  93.    if (world.model == "maps/hip3m1.bsp")
  94.       SetNewParms ();      // take away all stuff on starting new episode
  95.  
  96.     self.items = parm1;
  97.     self.health = parm2;
  98.     self.armorvalue = parm3;
  99.     self.ammo_shells = parm4;
  100.     self.ammo_nails = parm5;
  101.     self.ammo_rockets = parm6;
  102.     self.ammo_cells = parm7;
  103.     self.weapon = parm8;
  104.     self.armortype = parm9 * 0.01;
  105. };
  106.  
  107. /*
  108. ============
  109. FindIntermission
  110.  
  111. Returns the entity to view from
  112. ============
  113. */
  114. entity() FindIntermission =
  115. {
  116.     local    entity spot;
  117.     local    float cyc;
  118.  
  119. // look for info_intermission first
  120.     spot = find (world, classname, "info_intermission");
  121.     if (spot)
  122.     {    // pick a random one
  123.         cyc = random() * 4;
  124.         while (cyc > 1)
  125.         {
  126.             spot = find (spot, classname, "info_intermission");
  127.             if (!spot)
  128.                 spot = find (spot, classname, "info_intermission");
  129.             cyc = cyc - 1;
  130.         }
  131.         return spot;
  132.     }
  133.  
  134. // then look for the start position
  135.     spot = find (world, classname, "info_player_start");
  136.     if (spot)
  137.         return spot;
  138.  
  139. // testinfo_player_start is only found in regioned levels
  140.     spot = find (world, classname, "testplayerstart");
  141.     if (spot)
  142.         return spot;
  143.  
  144.     objerror ("FindIntermission: no spot");
  145. };
  146.  
  147.  
  148. string nextmap;
  149. void() GotoNextMap =
  150. {
  151.     if (cvar("samelevel"))    // if samelevel is set, stay on same level
  152.         changelevel (mapname);
  153.     else
  154.         changelevel (nextmap);
  155. };
  156.  
  157.  
  158. void() ExitIntermission =
  159. {
  160. // skip any text in deathmatch
  161.     if (deathmatch)
  162.     {
  163.         GotoNextMap ();
  164.         return;
  165.     }
  166.  
  167.     intermission_exittime = time + 1;
  168.     intermission_running = intermission_running + 1;
  169.  
  170. //
  171. // run some text if at the end of an episode
  172. //
  173.     if (intermission_running == 2)
  174.     {
  175.         if (world.model == "maps/e1m7.bsp")
  176.         {
  177.             WriteByte (MSG_ALL, SVC_CDTRACK);
  178.             WriteByte (MSG_ALL, 2);
  179.             WriteByte (MSG_ALL, 3);
  180.             if (!cvar("registered"))
  181.             {
  182.                 WriteByte (MSG_ALL, SVC_FINALE);
  183.                 WriteString (MSG_ALL, "As the corpse of the monstrous entity\nChthon sinks back into the lava whence\nit rose, you grip the Rune of Earth\nMagic tightly. Now that you have\nconquered the Dimension of the Doomed,\nrealm of Earth Magic, you are ready to\ncomplete your task in the other three\nhaunted lands of Quake. Or are you? If\nyou don't register Quake, you'll never\nknow what awaits you in the Realm of\nBlack Magic, the Netherworld, and the\nElder World!");
  184.             }
  185.             else
  186.             {
  187.                 WriteByte (MSG_ALL, SVC_FINALE);
  188.                 WriteString (MSG_ALL, "As the corpse of the monstrous entity\nChthon sinks back into the lava whence\nit rose, you grip the Rune of Earth\nMagic tightly. Now that you have\nconquered the Dimension of the Doomed,\nrealm of Earth Magic, you are ready to\ncomplete your task. A Rune of magic\npower lies at the end of each haunted\nland of Quake. Go forth, seek the\ntotality of the four Runes!");
  189.             }
  190.             return;
  191.         }
  192.         else if (world.model == "maps/e2m6.bsp")
  193.         {
  194.             WriteByte (MSG_ALL, SVC_CDTRACK);
  195.             WriteByte (MSG_ALL, 2);
  196.             WriteByte (MSG_ALL, 3);
  197.  
  198.             WriteByte (MSG_ALL, SVC_FINALE);
  199.             WriteString (MSG_ALL, "The Rune of Black Magic throbs evilly in\nyour hand and whispers dark thoughts\ninto your brain. You learn the inmost\nlore of the Hell-Mother; Shub-Niggurath!\nYou now know that she is behind all the\nterrible plotting which has led to so\nmuch death and horror. But she is not\ninviolate! Armed with this Rune, you\nrealize that once all four Runes are\ncombined, the gate to Shub-Niggurath's\nPit will open, and you can face the\nWitch-Goddess herself in her frightful\notherworld cathedral.");
  200.             return;
  201.         }
  202.         else if (world.model == "maps/e3m6.bsp")
  203.         {
  204.             WriteByte (MSG_ALL, SVC_CDTRACK);
  205.             WriteByte (MSG_ALL, 2);
  206.             WriteByte (MSG_ALL, 3);
  207.  
  208.             WriteByte (MSG_ALL, SVC_FINALE);
  209.             WriteString (MSG_ALL, "The charred viscera of diabolic horrors\nbubble viscously as you seize the Rune\nof Hell Magic. Its heat scorches your\nhand, and its terrible secrets blight\nyour mind. Gathering the shreds of your\ncourage, you shake the devil's shackles\nfrom your soul, and become ever more\nhard and determined to destroy the\nhideous creatures whose mere existence\nthreatens the souls and psyches of all\nthe population of Earth.");
  210.             return;
  211.         }
  212.         else if (world.model == "maps/e4m7.bsp")
  213.         {
  214.             WriteByte (MSG_ALL, SVC_CDTRACK);
  215.             WriteByte (MSG_ALL, 2);
  216.             WriteByte (MSG_ALL, 3);
  217.  
  218.             WriteByte (MSG_ALL, SVC_FINALE);
  219.             WriteString (MSG_ALL, "Despite the awful might of the Elder\nWorld, you have achieved the Rune of\nElder Magic, capstone of all types of\narcane wisdom. Beyond good and evil,\nbeyond life and death, the Rune\npulsates, heavy with import. Patient and\npotent, the Elder Being Shub-Niggurath\nweaves her dire plans to clear off all\nlife from the Earth, and bring her own\nfoul offspring to our world! For all the\ndwellers in these nightmare dimensions\nare her descendants! Once all Runes of\nmagic power are united, the energy\nbehind them will blast open the Gateway\nto Shub-Niggurath, and you can travel\nthere to foil the Hell-Mother's plots\nin person.");
  220.             return;
  221.         }
  222.  
  223. //HIPNOTIC
  224.       if (world.model == "maps/hip1m4.bsp")
  225.       {
  226.             WriteByte (MSG_ALL, SVC_CDTRACK);
  227.          WriteByte (MSG_ALL, 6);
  228.             WriteByte (MSG_ALL, 3);
  229.             WriteByte (MSG_ALL, SVC_FINALE);
  230. /*
  231.          **************************************
  232.          Deep within the bowels of the
  233.          Research Facility, you discover the
  234.          passage that the followers of Quake
  235.          have used to enter our world.
  236.          The bastards used some type of
  237.          gigantic teleporter to overload
  238.          one of our own slipgates!  As long as
  239.          this portal exists, Earth will never
  240.          be safe from Quake's cruel minions.
  241.  
  242.          If you can find the source of the
  243.          portal's power, you can shut it
  244.          down--possibly forever!  With only a
  245.          moment's consideration for your own
  246.          safety, you re-enter the dark domain,
  247.          knowing Hell would be a better fate
  248.          than experiencing the reign of Quake.
  249. */
  250.          WriteString (MSG_ALL, "Deep within the bowels of the\nResearch Facility, you discover the\npassage that the followers of Quake\nhave used to enter our world.\nThe bastards used some type of\ngigantic teleporter to overload\none of our own slipgates!  As long as\nthis portal exists, Earth will never\nbe safe from Quake's cruel minions." );
  251.          //WriteString (MSG_ALL, "If you can find the source of the\nportal's power, you can shut it\ndown--possibly forever!  With only a\nmoment's consideration for your own\nsafety, you re-enter the dark domain,\nknowing Hell would be a better fate\nthan experiencing the reign of Quake." );
  252.          return;
  253.         }
  254.         else if (world.model == "maps/hip2m5.bsp")
  255.         {
  256. /*
  257.          **************************************
  258.          After destroying the power generator,
  259.          you pass beyond the gate of Mortum's
  260.          Keep.  A wave of nausea suddenly flows
  261.          over you and you find yourself cast
  262.          out into a liquid void.  You float
  263.          lifelessly, yet aware, in a lavender
  264.          sea of energy.
  265.  
  266.          After what seems like an eternity,
  267.          you feel the presence of a diabolical
  268.          intelligence.  You are held helpless
  269.          for a moment as your mind is open to
  270.          that of Armagon--Quake's General and
  271.          master of this realm.  Recognizing
  272.          you as the one who foiled his
  273.          attempt to conquer Earth, a hellish
  274.          howl fills your mind and blots out
  275.          all consciousness.  When you awake,
  276.          you find yourself on the shores of
  277.          reality, but in a time and place
  278.          unknown to you.
  279. */
  280.          WriteByte (MSG_ALL, SVC_CDTRACK);
  281.          WriteByte (MSG_ALL, 6);
  282.             WriteByte (MSG_ALL, 3);
  283.  
  284.             WriteByte (MSG_ALL, SVC_FINALE);
  285.          WriteString (MSG_ALL, "After destroying the power generator,\nyou pass beyond the gate of Mortum's\nKeep.  A wave of nausea suddenly flows\nover you and you find yourself cast\nout into a liquid void.  You float\nlifelessly, yet aware, in a lavender\nsea of energy." );
  286.          //WriteString (MSG_ALL, "After what seems like an eternity,\nyou feel the presence of a diabolical\nintelligence.  You are held helpless\nfor a moment as your mind is open to\nthat of Armagon--Quake's General and\nmaster of this realm.  Recognizing\nyou as the one who foiled his\nattempts to conquer Earth, a hellish\nhowl fills your mind and blots out\nall consciousness.  When you awake,\nyou find yourself on the shores of\nreality, but in a time and place\nunknown to you." );
  287.          return;
  288.         }
  289.       else if (world.model == "maps/hipend.bsp")
  290.       {
  291. /*
  292.          **************************************
  293.          After the last echoes of Armagon's
  294.          death yell fade away, you breathe a
  295.          heavy sigh of relief.  With the loss
  296.          of his magic, Armagon's fortress
  297.          begins to collapse.  The rift he
  298.          created to send his grisly troops
  299.          through time slowly closes and seals
  300.          itself forever.  In the chaos that
  301.          ensues, a wall collapses, revealing
  302.          one remaining time portal.  With your
  303.          chances to escape rapidly growing
  304.          slim, you race for the portal,
  305.          mindless of your destination.  In a
  306.          flash of light, you find yourself
  307.          back at Command HQ, safe and sound.
  308.  
  309.          Congratulations!  You are victorious!
  310.          The minions of Quake have once again
  311.          fallen before your mighty hand.
  312.          Is this the last you will see of
  313.          Quake's hellions?
  314.  
  315.          Only time will tell...
  316. */
  317.          WriteByte (MSG_ALL, SVC_CDTRACK);
  318.          WriteByte (MSG_ALL, 2);
  319.             WriteByte (MSG_ALL, 3);
  320.  
  321.             WriteByte (MSG_ALL, SVC_FINALE);
  322.          WriteString (MSG_ALL, "After the last echoes of Armagon's\ndeath yell fade away, you breathe a\nheavy sigh of relief.  With the loss\nof his magic, Armagon's fortress\nbegins to collapse.  The rift he\ncreated to send his grisly troops\nthrough time slowly closes and seals\nitself forever.  In the chaos that\nensues, a wall collapses, revealing\none remaining time portal.  With your\nchances to escape rapidly growing\nslim, you race for the portal,\nmindless of your destination.  In a\nflash of light, you find yourself\nback at Command HQ, safe and sound." );
  323.          //WriteString (MSG_ALL, "Congratulations!  You are victorious!\nThe minions of Quake have once again\nfallen before your mighty hand.\nIs this the last you will see of\nQuake's hellions?\n\nOnly time will tell..." );
  324.          //intermission_exittime = time + 10000000;  // never allow exit
  325.             return;
  326.         }
  327.       GotoNextMap();
  328.     }
  329.  
  330.     if (intermission_running == 3)
  331.     {
  332.         if (!cvar("registered"))
  333.         {    // shareware episode has been completed, go to sell screen
  334.             WriteByte (MSG_ALL, SVC_SELLSCREEN);
  335.             return;
  336.         }
  337.  
  338.         if ( (serverflags&15) == 15)
  339.         {
  340.             WriteByte (MSG_ALL, SVC_FINALE);
  341.             WriteString (MSG_ALL, "Now, you have all four Runes. You sense\ntremendous invisible forces moving to\nunseal ancient barriers. Shub-Niggurath\nhad hoped to use the Runes Herself to\nclear off the Earth, but now instead,\nyou will use them to enter her home and\nconfront her as an avatar of avenging\nEarth-life. If you defeat her, you will\nbe remembered forever as the savior of\nthe planet. If she conquers, it will be\nas if you had never been born.");
  342.             return;
  343.         }
  344.  
  345. //HIPNOTIC
  346.       if (world.model == "maps/hip1m4.bsp")
  347.       {
  348.          WriteByte (MSG_ALL, SVC_FINALE);
  349.          WriteString (MSG_ALL, "If you can find the source of the\nportal's power, you can shut it\ndown--possibly forever!  With only a\nmoment's consideration for your own\nsafety, you re-enter the dark domain,\nknowing Hell would be a better fate\nthan experiencing the reign of Quake." );
  350.          return;
  351.         }
  352.         else if (world.model == "maps/hip2m5.bsp")
  353.         {
  354.          WriteByte (MSG_ALL, SVC_FINALE);
  355.          WriteString (MSG_ALL, "After what seems like an eternity,\nyou feel the presence of a diabolical\nintelligence.  You are held helpless\nfor a moment as your mind is open to\nthat of Armagon--Quake's General and\nmaster of this realm.  Recognizing\nyou as the one who foiled his\nattempt to conquer Earth, a hellish\nhowl fills your mind and blots out\nall consciousness.  When you awake,\nyou find yourself on the shores of\nreality, but in a time and place\nunknown to you." );
  356.          return;
  357.         }
  358.       else if (world.model == "maps/hipend.bsp")
  359.       {
  360.          WriteByte (MSG_ALL, SVC_FINALE);
  361.          WriteString (MSG_ALL, "Congratulations!  You are victorious!\nThe minions of Quake have once again\nfallen before your mighty hand.\nIs this the last you will see of\nQuake's hellions?\n\nOnly time will tell..." );
  362.          intermission_exittime = time + 10000000;  // never allow exit
  363.             return;
  364.         }
  365.    }
  366.  
  367.     GotoNextMap();
  368. };
  369.  
  370. /*
  371. ============
  372. IntermissionThink
  373.  
  374. When the player presses attack or jump, change to the next level
  375. ============
  376. */
  377. void() IntermissionThink =
  378. {
  379.     if (time < intermission_exittime)
  380.         return;
  381.  
  382.     if (!self.button0 && !self.button1 && !self.button2)
  383.         return;
  384.  
  385.     ExitIntermission ();
  386. };
  387.  
  388. void() execute_changelevel =
  389. {
  390.     local entity    pos;
  391.  
  392.     intermission_running = 1;
  393.  
  394. // enforce a wait time before allowing changelevel
  395.     if (deathmatch)
  396.         intermission_exittime = time + 5;
  397.     else
  398.         intermission_exittime = time + 2;
  399.  
  400.     WriteByte (MSG_ALL, SVC_CDTRACK);
  401.    WriteByte (MSG_ALL, 9);
  402.     WriteByte (MSG_ALL, 3);
  403.  
  404.     pos = FindIntermission ();
  405.  
  406.     other = find (world, classname, "player");
  407.     while (other != world)
  408.     {
  409.         other.view_ofs = '0 0 0';
  410.         other.angles = other.v_angle = pos.mangle;
  411.         other.fixangle = TRUE;        // turn this way immediately
  412.         other.nextthink = time + 0.5;
  413.         other.takedamage = DAMAGE_NO;
  414.         other.solid = SOLID_NOT;
  415.         other.movetype = MOVETYPE_NONE;
  416.         other.modelindex = 0;
  417.         setorigin (other, pos.origin);
  418.         other = find (other, classname, "player");
  419.     }
  420.  
  421.     WriteByte (MSG_ALL, SVC_INTERMISSION);
  422. };
  423.  
  424.  
  425. void() changelevel_touch =
  426. {
  427.     local entity    pos;
  428.  
  429.     if (other.classname != "player")
  430.         return;
  431.  
  432.    if ((cvar("noexit") == 1) || ((cvar("noexit") == 2) && (mapname != "start")))
  433.     {
  434.         T_Damage (other, self, self, 50000);
  435.         return;
  436.     }
  437.  
  438.    if (coop || deathmatch)
  439.     {
  440.         bprint (other.netname);
  441.         bprint (" exited the level\n");
  442.     }
  443.  
  444.     nextmap = self.map;
  445.  
  446.     SUB_UseTargets ();
  447.  
  448.     if ( (self.spawnflags & 1) && (deathmatch == 0) )
  449.     {    // NO_INTERMISSION
  450.         GotoNextMap();
  451.         return;
  452.     }
  453.  
  454.     self.touch = SUB_Null;
  455.  
  456. // we can't move people right now, because touch functions are called
  457. // in the middle of C movement code, so set a think time to do it
  458.     self.think = execute_changelevel;
  459.     self.nextthink = time + 0.1;
  460. };
  461.  
  462. /*QUAKED trigger_changelevel (0.5 0.5 0.5) ? NO_INTERMISSION
  463. When the player touches this, he gets sent to the map listed in the "map" variable.  Unless the NO_INTERMISSION flag is set, the view will go to the info_intermission spot and display stats.
  464. */
  465. void() trigger_changelevel =
  466. {
  467.     if (!self.map)
  468.         objerror ("chagnelevel trigger doesn't have map");
  469.  
  470.     InitTrigger ();
  471.     self.touch = changelevel_touch;
  472. };
  473.  
  474.  
  475. /*
  476. =============================================================================
  477.  
  478.                 PLAYER GAME EDGE FUNCTIONS
  479.  
  480. =============================================================================
  481. */
  482.  
  483. void() set_suicide_frame;
  484.  
  485. // called by ClientKill and DeadThink
  486. void() respawn =
  487. {
  488.     if (coop)
  489.     {
  490.         // make a copy of the dead body for appearances sake
  491.         CopyToBodyQue (self);
  492.         // get the spawn parms as they were at level start
  493.         setspawnparms (self);
  494.         // respawn
  495.         PutClientInServer ();
  496.     }
  497.     else if (deathmatch)
  498.     {
  499.         // make a copy of the dead body for appearances sake
  500.         CopyToBodyQue (self);
  501.         // set default spawn parms
  502.         SetNewParms ();
  503.         // respawn
  504.         PutClientInServer ();
  505.     }
  506.     else
  507.     {    // restart the entire server
  508.         localcmd ("restart\n");
  509.     }
  510. };
  511.  
  512.  
  513. /*
  514. ============
  515. ClientKill
  516.  
  517. Player entered the suicide command
  518. ============
  519. */
  520. void() ClientKill =
  521. {
  522.     bprint (self.netname);
  523.     bprint (" suicides\n");
  524.     set_suicide_frame ();
  525.     self.modelindex = modelindex_player;
  526.     self.frags = self.frags - 2;    // extra penalty
  527.     respawn ();
  528. };
  529.  
  530. float(vector v) CheckSpawnPoint =
  531. {
  532.     return FALSE;
  533. };
  534.  
  535. /*
  536. ============
  537. SelectSpawnPoint
  538.  
  539. Returns the entity to spawn at
  540. ============
  541. */
  542. entity() SelectSpawnPoint =
  543. {
  544.     local    entity spot;
  545.    local entity thing;
  546.     local    float  pcount;
  547.  
  548. // testinfo_player_start is only found in regioned levels
  549.     spot = find (world, classname, "testplayerstart");
  550.     if (spot)
  551.         return spot;
  552.  
  553. // choose a info_player_deathmatch point
  554.     if (coop)
  555.     {
  556.         lastspawn = find(lastspawn, classname, "info_player_coop");
  557.         if (lastspawn == world)
  558.             lastspawn = find (lastspawn, classname, "info_player_start");
  559.         if (lastspawn != world)
  560.             return lastspawn;
  561.     }
  562.     else if (deathmatch)
  563.     {
  564.       spot = lastspawn;
  565.         while (1)
  566.         {
  567.             spot = find(spot, classname, "info_player_deathmatch");
  568.             if (spot != world)
  569.             {
  570.                 if (spot == lastspawn)
  571.                     return lastspawn;
  572.                 pcount = 0;
  573.                 thing = findradius(spot.origin, 32);
  574.                 while(thing)
  575.                 {
  576.                     if (thing.classname == "player")
  577.                         pcount = pcount + 1;
  578.                     thing = thing.chain;
  579.                 }
  580.                 if (pcount == 0)
  581.                 {
  582.                     lastspawn = spot;
  583.                     return spot;
  584.                 }
  585.             }
  586.         }
  587.     }
  588.  
  589.     if (serverflags)
  590.     {    // return with a rune to start
  591.         spot = find (world, classname, "info_player_start2");
  592.         if (spot)
  593.             return spot;
  594.     }
  595.  
  596.     spot = find (world, classname, "info_player_start");
  597.     if (!spot)
  598.         error ("PutClientInServer: no info_player_start on level");
  599.  
  600.     return spot;
  601. };
  602.  
  603. /*
  604. ===========
  605. PutClientInServer
  606.  
  607. called each time a player is spawned
  608. ============
  609. */
  610. void() DecodeLevelParms;
  611. void() PlayerDie;
  612.  
  613.  
  614. void() PutClientInServer =
  615. {
  616.     local    entity spot;
  617.  
  618.    spot = SelectSpawnPoint ();
  619.  
  620.    self.classname = "player";
  621.     self.health = 100;
  622.     self.takedamage = DAMAGE_AIM;
  623.     self.solid = SOLID_SLIDEBOX;
  624.     self.movetype = MOVETYPE_WALK;
  625.     self.show_hostile = 0;
  626.     self.max_health = 100;
  627.     self.flags = FL_CLIENT;
  628.     self.air_finished = time + 12;
  629.     self.dmg = 2;           // initial water damage
  630.     self.super_damage_finished = 0;
  631.     self.radsuit_finished = 0;
  632.     self.invisible_finished = 0;
  633.     self.invincible_finished = 0;
  634.     self.effects = 0;
  635.     self.invincible_time = 0;
  636.     //JIM
  637.     self.wetsuit_finished = 0;
  638.    //MED
  639.    self.empathy_finished = 0;
  640.    //MED
  641.    self.items2 = 0;
  642.    self.gravity = 1.0;
  643.  
  644.  
  645.     DecodeLevelParms ();
  646.  
  647.     W_SetCurrentAmmo ();
  648.  
  649.     self.attack_finished = time;
  650.     self.th_pain = player_pain;
  651.     self.th_die = PlayerDie;
  652.  
  653.     self.deadflag = DEAD_NO;
  654. // paustime is set by teleporters to keep the player from moving a while
  655.     self.pausetime = 0;
  656.  
  657. //   spot = SelectSpawnPoint ();
  658.  
  659.     self.origin = spot.origin + '0 0 1';
  660.     self.angles = spot.angles;
  661.     self.fixangle = TRUE;        // turn this way immediately
  662.  
  663.    //JIM
  664.    // Clear out velocity so you're not launched into the air
  665.    // when you respawn.
  666.    self.velocity = '0 0 0';
  667.  
  668. // oh, this is a hack!
  669.    setmodel (self, "progs/playham.mdl");
  670.    modelindex_hammer = self.modelindex;
  671.  
  672.    setmodel (self, "progs/eyes.mdl");
  673.     modelindex_eyes = self.modelindex;
  674.  
  675.     setmodel (self, "progs/player.mdl");
  676.     modelindex_player = self.modelindex;
  677.  
  678.     setsize (self, VEC_HULL_MIN, VEC_HULL_MAX);
  679.  
  680.     self.view_ofs = '0 0 22';
  681.  
  682.     player_stand1 ();
  683.  
  684.     if (deathmatch || coop)
  685.     {
  686.         makevectors(self.angles);
  687.         spawn_tfog (self.origin + v_forward*20);
  688.     }
  689.  
  690.     spawn_tdeath (self.origin, self);
  691. };
  692.  
  693.  
  694. /*
  695. =============================================================================
  696.  
  697.                 QUAKED FUNCTIONS
  698.  
  699. =============================================================================
  700. */
  701.  
  702.  
  703. /*QUAKED info_player_start (1 0 0) (-16 -16 -24) (16 16 24)
  704. The normal starting point for a level.
  705. */
  706. void() info_player_start =
  707. {
  708. };
  709.  
  710.  
  711. /*QUAKED info_player_start2 (1 0 0) (-16 -16 -24) (16 16 24)
  712. Only used on start map for the return point from an episode.
  713. */
  714. void() info_player_start2 =
  715. {
  716. };
  717.  
  718.  
  719. /*
  720. saved out by quaked in region mode
  721. */
  722. void() testplayerstart =
  723. {
  724. };
  725.  
  726. /*QUAKED info_player_deathmatch (1 0 1) (-16 -16 -24) (16 16 24)
  727. potential spawning position for deathmatch games
  728. */
  729. void() info_player_deathmatch =
  730. {
  731. };
  732.  
  733. /*QUAKED info_player_coop (1 0 1) (-16 -16 -24) (16 16 24)
  734. potential spawning position for coop games
  735. */
  736. void() info_player_coop =
  737. {
  738. };
  739.  
  740. /*
  741. ===============================================================================
  742.  
  743. RULES
  744.  
  745. ===============================================================================
  746. */
  747.  
  748. /*
  749. go to the next level for deathmatch
  750. only called if a time or frag limit has expired
  751. */
  752. void() NextLevel =
  753. {
  754.     local entity o;
  755.  
  756. //HIPNOTIC
  757. //Commented out so that timelimit and fraglimit work on start map
  758.    /*
  759.     if (mapname == "start")
  760.     {
  761.         if (!cvar("registered"))
  762.         {
  763.             mapname = "e1m1";
  764.         }
  765.         else if (!(serverflags & 1))
  766.         {
  767.             mapname = "e1m1";
  768.          serverflags = serverflags | 1;
  769.         }
  770.         else if (!(serverflags & 2))
  771.         {
  772.             mapname = "e2m1";
  773.          serverflags = serverflags | 2;
  774.         }
  775.         else if (!(serverflags & 4))
  776.         {
  777.             mapname = "e3m1";
  778.          serverflags = serverflags | 4;
  779.         }
  780.         else if (!(serverflags & 8))
  781.         {
  782.             mapname = "e4m1";
  783.          serverflags = serverflags - 7;
  784.         }
  785.  
  786.         o = spawn();
  787.         o.map = mapname;
  788.     }
  789.     else
  790.     {
  791. */
  792.         // find a trigger changelevel
  793.         o = find(world, classname, "trigger_changelevel");
  794.  
  795.         // go back to start if no trigger_changelevel
  796.         if (!o)
  797.         {
  798.             mapname = "start";
  799.             o = spawn();
  800.             o.map = mapname;
  801.         }
  802. //   }
  803.  
  804.     nextmap = o.map;
  805.     gameover = TRUE;
  806.  
  807.     if (o.nextthink < time)
  808.     {
  809.         o.think = execute_changelevel;
  810.         o.nextthink = time + 0.1;
  811.     }
  812. };
  813.  
  814. /*
  815. ============
  816. CheckRules
  817.  
  818. Exit deathmatch games upon conditions
  819. ============
  820. */
  821. void() CheckRules =
  822. {
  823.     local    float        timelimit;
  824.     local    float        fraglimit;
  825.  
  826.     if (gameover)    // someone else quit the game already
  827.         return;
  828.  
  829.     timelimit = cvar("timelimit") * 60;
  830.     fraglimit = cvar("fraglimit");
  831.  
  832.     if (timelimit && time >= timelimit)
  833.     {
  834.         NextLevel ();
  835.         return;
  836.     }
  837.  
  838.     if (fraglimit && self.frags >= fraglimit)
  839.     {
  840.         NextLevel ();
  841.         return;
  842.     }
  843. };
  844.  
  845. //============================================================================
  846.  
  847. void() PlayerDeathThink =
  848. {
  849.     local entity    old_self;
  850.     local float        forward;
  851.  
  852.     if ((self.flags & FL_ONGROUND))
  853.     {
  854.         forward = vlen (self.velocity);
  855.         forward = forward - 20;
  856.         if (forward <= 0)
  857.             self.velocity = '0 0 0';
  858.         else
  859.             self.velocity = forward * normalize(self.velocity);
  860.     }
  861.  
  862. // wait for all buttons released
  863.     if (self.deadflag == DEAD_DEAD)
  864.     {
  865.         if (self.button2 || self.button1 || self.button0)
  866.             return;
  867.         self.deadflag = DEAD_RESPAWNABLE;
  868.         return;
  869.     }
  870.  
  871. // wait for any button down
  872.     if (!self.button2 && !self.button1 && !self.button0)
  873.         return;
  874.  
  875.     self.button0 = 0;
  876.     self.button1 = 0;
  877.     self.button2 = 0;
  878.     respawn();
  879. };
  880.  
  881.  
  882. void() PlayerJump =
  883. {
  884.     local vector start, end;
  885.  
  886.     if (self.flags & FL_WATERJUMP)
  887.         return;
  888.  
  889.     if (self.waterlevel >= 2)
  890.     {
  891.         if (self.watertype == CONTENT_WATER)
  892.             self.velocity_z = 100;
  893.         else if (self.watertype == CONTENT_SLIME)
  894.             self.velocity_z = 80;
  895.         else
  896.             self.velocity_z = 50;
  897.  
  898. // play swiming sound
  899.         if (self.swim_flag < time)
  900.         {
  901.             self.swim_flag = time + 1;
  902.             if (random() < 0.5)
  903.                 sound (self, CHAN_BODY, "misc/water1.wav", 1, ATTN_NORM);
  904.             else
  905.                 sound (self, CHAN_BODY, "misc/water2.wav", 1, ATTN_NORM);
  906.         }
  907.  
  908.         return;
  909.     }
  910.  
  911.     if (!(self.flags & FL_ONGROUND))
  912.         return;
  913.  
  914.     if ( !(self.flags & FL_JUMPRELEASED) )
  915.         return;        // don't pogo stick
  916.  
  917.     self.flags = self.flags - (self.flags & FL_JUMPRELEASED);
  918.  
  919.     self.flags = self.flags - FL_ONGROUND;    // don't stairwalk
  920.  
  921.     self.button2 = 0;
  922. // player jumping sound
  923.     sound (self, CHAN_BODY, "player/plyrjmp8.wav", 1, ATTN_NORM);
  924.     self.velocity_z = self.velocity_z + 270;
  925. };
  926.  
  927.  
  928. /*
  929. ===========
  930. WaterMove
  931.  
  932. ============
  933. */
  934. .float    dmgtime;
  935.  
  936. void() WaterMove =
  937. {
  938. //dprint (ftos(self.waterlevel));
  939.     if (self.movetype == MOVETYPE_NOCLIP)
  940.         return;
  941.     if (self.health < 0)
  942.         return;
  943.  
  944.     if (self.waterlevel != 3)
  945.     {
  946.         if (self.air_finished < time)
  947.             sound (self, CHAN_VOICE, "player/gasp2.wav", 1, ATTN_NORM);
  948.         else if (self.air_finished < time + 9)
  949.             sound (self, CHAN_VOICE, "player/gasp1.wav", 1, ATTN_NORM);
  950.         self.air_finished = time + 12;
  951.         self.dmg = 2;
  952.     }
  953.     else if (self.air_finished < time)
  954.     {    // drown!
  955.         if (self.pain_finished < time)
  956.         {
  957.             self.dmg = self.dmg + 2;
  958.             if (self.dmg > 15)
  959.                 self.dmg = 10;
  960.             T_Damage (self, world, world, self.dmg);
  961.             self.pain_finished = time + 1;
  962.         }
  963.     }
  964.  
  965.     if (!self.waterlevel)
  966.     {
  967.         if (self.flags & FL_INWATER)
  968.         {
  969.             // play leave water sound
  970.             sound (self, CHAN_BODY, "misc/outwater.wav", 1, ATTN_NORM);
  971.             self.flags = self.flags - FL_INWATER;
  972.         }
  973.         return;
  974.     }
  975.  
  976.     if (self.watertype == CONTENT_LAVA)
  977.     {    // do damage
  978.         if (self.dmgtime < time)
  979.         {
  980.             if (self.radsuit_finished > time)
  981.                 self.dmgtime = time + 1;
  982.             else
  983.                 self.dmgtime = time + 0.2;
  984.  
  985.             T_Damage (self, world, world, 10*self.waterlevel);
  986.         }
  987.     }
  988.     else if (self.watertype == CONTENT_SLIME)
  989.     {    // do damage
  990.         if (self.dmgtime < time && self.radsuit_finished < time)
  991.         {
  992.             self.dmgtime = time + 1;
  993.             T_Damage (self, world, world, 4*self.waterlevel);
  994.         }
  995.     }
  996.  
  997.     if ( !(self.flags & FL_INWATER) )
  998.     {
  999.  
  1000. // player enter water sound
  1001.  
  1002.         if (self.watertype == CONTENT_LAVA)
  1003.             sound (self, CHAN_BODY, "player/inlava.wav", 1, ATTN_NORM);
  1004.         if (self.watertype == CONTENT_WATER)
  1005.             sound (self, CHAN_BODY, "player/inh2o.wav", 1, ATTN_NORM);
  1006.         if (self.watertype == CONTENT_SLIME)
  1007.             sound (self, CHAN_BODY, "player/slimbrn2.wav", 1, ATTN_NORM);
  1008.  
  1009.         self.flags = self.flags + FL_INWATER;
  1010.         self.dmgtime = 0;
  1011.     }
  1012.  
  1013.     if (! (self.flags & FL_WATERJUMP) )
  1014.         self.velocity = self.velocity - 0.8*self.waterlevel*frametime*self.velocity;
  1015. };
  1016.  
  1017. void() CheckWaterJump =
  1018. {
  1019.     local vector start, end;
  1020.  
  1021. // check for a jump-out-of-water
  1022.     makevectors (self.angles);
  1023.     start = self.origin;
  1024.     start_z = start_z + 8;
  1025.     v_forward_z = 0;
  1026.     normalize(v_forward);
  1027.     end = start + v_forward*24;
  1028.     traceline (start, end, TRUE, self);
  1029.     if (trace_fraction < 1)
  1030.     {    // solid at waist
  1031.         start_z = start_z + self.maxs_z - 8;
  1032.         end = start + v_forward*24;
  1033.         self.movedir = trace_plane_normal * -50;
  1034.         traceline (start, end, TRUE, self);
  1035.         if (trace_fraction == 1)
  1036.         {    // open at eye level
  1037.             self.flags = self.flags | FL_WATERJUMP;
  1038.             self.velocity_z = 225;
  1039.             self.flags = self.flags - (self.flags & FL_JUMPRELEASED);
  1040.             self.teleport_time = time + 2;    // safety net
  1041.             return;
  1042.         }
  1043.     }
  1044. };
  1045.  
  1046. /*
  1047. ================
  1048. PlayerPreThink
  1049.  
  1050. Called every frame before physics are run
  1051. ================
  1052. */
  1053. //MED 01/17/97
  1054. void(float num_bubbles) DeathBubbles;
  1055. void() PlayerPreThink =
  1056. {
  1057.     local    float    mspeed, aspeed;
  1058.     local    float    r;
  1059.  
  1060.     if (intermission_running)
  1061.     {
  1062.       earthquake_prethink();
  1063.       IntermissionThink ();   // otherwise a button could be missed between
  1064.         return;                    // the think tics
  1065.     }
  1066.  
  1067.     if (self.view_ofs == '0 0 0')
  1068.         return;        // intermission or finale
  1069.  
  1070. //JIM
  1071.    // Kill player on Edge of Oblivion
  1072.    if ( ( self.origin_z < -1250 ) && (world.model == "maps/hipdm1.bsp") &&
  1073.       ( self.health > 0 ) )
  1074.       {
  1075.  
  1076.       self.deathtype = "falling";
  1077.  
  1078.       if (self.invincible_finished >= time)
  1079.          {
  1080.          self.invincible_finished = 0;
  1081.          self.items = self.items - (self.items & IT_INVULNERABILITY);
  1082.          self.invincible_time = 0;
  1083.             self.invincible_finished = 0;
  1084.          self.effects = self.effects - (self.effects & EF_DIMLIGHT);
  1085.          }
  1086.       T_Damage( self, self, world, self.health + 1000 );
  1087.       }
  1088.  
  1089.     //JIM
  1090. //   if (!deathmatch)
  1091. //      {
  1092.       earthquake_prethink();
  1093. //      }
  1094.  
  1095.     makevectors (self.v_angle);        // is this still used
  1096.  
  1097.     CheckRules ();
  1098.     WaterMove ();
  1099.  
  1100.     //JIM
  1101.     //WETSUIT
  1102.     if (self.wetsuit_finished > time)
  1103.         {
  1104.         if (self.waterlevel==2)
  1105.             {
  1106.             self.velocity = self.velocity * 1.25;
  1107.             }
  1108.         if (self.waterlevel==3)
  1109.             {
  1110.             self.velocity = self.velocity * 1.5;
  1111.             }
  1112.       if (self.waterlevel >= 2)
  1113.          {
  1114.          // play scuba sound
  1115.          if (self.swim_flag < time)
  1116.             {
  1117.             self.swim_flag = time + 7;
  1118.             sound (self, CHAN_BODY, "misc/wetsuit.wav", 1, ATTN_NORM);
  1119.             }
  1120.          //MED 01/17/97
  1121.          else
  1122.             {
  1123.             if (fabs(self.swim_flag - time - 6)<0.04)
  1124.                {
  1125.                DeathBubbles(1);
  1126.                }
  1127.             else if (fabs(self.swim_flag - time - 5.5)<0.04)
  1128.                {
  1129.                DeathBubbles(1);
  1130.                }
  1131.             else if (fabs(self.swim_flag - time - 5)<0.04)
  1132.                {
  1133.                DeathBubbles(1);
  1134.                }
  1135.             }
  1136.          }
  1137.      }
  1138.  
  1139.     if (self.waterlevel == 2)
  1140.         CheckWaterJump ();
  1141.  
  1142.     if (self.deadflag >= DEAD_DEAD)
  1143.     {
  1144.         PlayerDeathThink ();
  1145.         return;
  1146.     }
  1147.  
  1148.     if (self.deadflag == DEAD_DYING)
  1149.         return;    // dying, so do nothing
  1150.  
  1151.     if (self.button2)
  1152.     {
  1153.         PlayerJump ();
  1154.     }
  1155.     else
  1156.         self.flags = self.flags | FL_JUMPRELEASED;
  1157.  
  1158. // teleporters can force a non-moving pause time
  1159.     if (time < self.pausetime)
  1160.         self.velocity = '0 0 0';
  1161.  
  1162. // Grapple:  Grapple uses no ammo either.
  1163.    if(time > self.attack_finished && self.currentammo == 0 && self.weapon != IT_AXE && self.weapon != IT_MJOLNIR && self.weapon != IT_MORNINGSTAR)
  1164.     {
  1165.         self.weapon = W_BestWeapon ();
  1166.         W_SetCurrentAmmo ();
  1167.     }
  1168. };
  1169.  
  1170. /*
  1171. ================
  1172. CheckPowerups
  1173.  
  1174. Check for turning off powerups
  1175. ================
  1176. */
  1177. void() CheckPowerups =
  1178. {
  1179.     if (self.health <= 0)
  1180.         return;
  1181.  
  1182. // invisibility
  1183.     if (self.invisible_finished)
  1184.     {
  1185. // sound and screen flash when items starts to run out
  1186.         if (self.invisible_sound < time)
  1187.         {
  1188.             sound (self, CHAN_AUTO, "items/inv3.wav", 0.5, ATTN_IDLE);
  1189.             self.invisible_sound = time + ((random() * 3) + 1);
  1190.         }
  1191.  
  1192.  
  1193.         if (self.invisible_finished < time + 3)
  1194.         {
  1195.             if (self.invisible_time == 1)
  1196.             {
  1197.                 sprint (self, "Ring of Shadows magic is fading\n");
  1198.                 stuffcmd (self, "bf\n");
  1199.                 sound (self, CHAN_AUTO, "items/inv2.wav", 1, ATTN_NORM);
  1200.                 self.invisible_time = time + 1;
  1201.             }
  1202.  
  1203.             if (self.invisible_time < time)
  1204.             {
  1205.                 self.invisible_time = time + 1;
  1206.                 stuffcmd (self, "bf\n");
  1207.             }
  1208.         }
  1209.  
  1210.         if (self.invisible_finished < time)
  1211.         {    // just stopped
  1212.             self.items = self.items - IT_INVISIBILITY;
  1213.             self.invisible_finished = 0;
  1214.             self.invisible_time = 0;
  1215.         }
  1216.  
  1217.     // use the eyes
  1218.         self.frame = 0;
  1219.         self.modelindex = modelindex_eyes;
  1220.     }
  1221. //MED 12/04/96 added mjolnir stuff
  1222.    else if (self.weapon == IT_MJOLNIR)
  1223.       self.modelindex = modelindex_hammer;   // don't use eyes
  1224.    else
  1225.         self.modelindex = modelindex_player;    // don't use eyes
  1226.  
  1227. // invincibility
  1228.     if (self.invincible_finished)
  1229.     {
  1230. // sound and screen flash when items starts to run out
  1231.         if (self.invincible_finished < time + 3)
  1232.         {
  1233.             if (self.invincible_time == 1)
  1234.             {
  1235.                 sprint (self, "Protection is almost burned out\n");
  1236.                 stuffcmd (self, "bf\n");
  1237.                 sound (self, CHAN_AUTO, "items/protect2.wav", 1, ATTN_NORM);
  1238.                 self.invincible_time = time + 1;
  1239.             }
  1240.  
  1241.             if (self.invincible_time < time)
  1242.             {
  1243.                 self.invincible_time = time + 1;
  1244.                 stuffcmd (self, "bf\n");
  1245.             }
  1246.         }
  1247.  
  1248.         if (self.invincible_finished < time)
  1249.         {    // just stopped
  1250.             self.items = self.items - IT_INVULNERABILITY;
  1251.             self.invincible_time = 0;
  1252.             self.invincible_finished = 0;
  1253.         }
  1254.         if (self.invincible_finished > time)
  1255.             self.effects = self.effects | EF_DIMLIGHT;
  1256.         else
  1257.             self.effects = self.effects - (self.effects & EF_DIMLIGHT);
  1258.     }
  1259.  
  1260. // super damage
  1261.     if (self.super_damage_finished)
  1262.     {
  1263.  
  1264. // sound and screen flash when items starts to run out
  1265.  
  1266.         if (self.super_damage_finished < time + 3)
  1267.         {
  1268.             if (self.super_time == 1)
  1269.             {
  1270.                 sprint (self, "Quad Damage is wearing off\n");
  1271.                 stuffcmd (self, "bf\n");
  1272.                 sound (self, CHAN_AUTO, "items/damage2.wav", 1, ATTN_NORM);
  1273.                 self.super_time = time + 1;
  1274.             }
  1275.  
  1276.             if (self.super_time < time)
  1277.             {
  1278.                 self.super_time = time + 1;
  1279.                 stuffcmd (self, "bf\n");
  1280.             }
  1281.         }
  1282.  
  1283.         if (self.super_damage_finished < time)
  1284.         {    // just stopped
  1285.             self.items = self.items - IT_QUAD;
  1286.             self.super_damage_finished = 0;
  1287.             self.super_time = 0;
  1288.         }
  1289.         if (self.super_damage_finished > time)
  1290.             self.effects = self.effects | EF_DIMLIGHT;
  1291.         else
  1292.             self.effects = self.effects - (self.effects & EF_DIMLIGHT);
  1293.     }
  1294.  
  1295. // suit
  1296.     if (self.radsuit_finished)
  1297.     {
  1298.         self.air_finished = time + 12;        // don't drown
  1299.  
  1300. // sound and screen flash when items starts to run out
  1301.         if (self.radsuit_finished < time + 3)
  1302.         {
  1303.             if (self.rad_time == 1)
  1304.             {
  1305.                 sprint (self, "Air supply in Biosuit expiring\n");
  1306.                 stuffcmd (self, "bf\n");
  1307.                 sound (self, CHAN_AUTO, "items/suit2.wav", 1, ATTN_NORM);
  1308.                 self.rad_time = time + 1;
  1309.             }
  1310.  
  1311.             if (self.rad_time < time)
  1312.             {
  1313.                 self.rad_time = time + 1;
  1314.                 stuffcmd (self, "bf\n");
  1315.             }
  1316.         }
  1317.  
  1318.         if (self.radsuit_finished < time)
  1319.         {    // just stopped
  1320.             self.items = self.items - IT_SUIT;
  1321.             self.rad_time = 0;
  1322.             self.radsuit_finished = 0;
  1323.         }
  1324.     }
  1325.  
  1326. //JIM
  1327. // wetsuit
  1328.     if (self.wetsuit_finished)
  1329.     {
  1330.     self.air_finished = time + 12;        // don't drown
  1331.  
  1332.     // sound and screen flash when items starts to run out
  1333.     if (self.wetsuit_finished < time + 3)
  1334.         {
  1335.             if (self.wetsuit_time == 1)
  1336.             {
  1337.                 sprint (self, "Air supply in Wetsuit is running out\n");
  1338.                 stuffcmd (self, "bf\n");
  1339.                 sound (self, CHAN_AUTO, "items/suit2.wav", 1, ATTN_NORM);
  1340.                 self.wetsuit_time = time + 1;
  1341.             }
  1342.  
  1343.             if (self.wetsuit_time < time)
  1344.             {
  1345.                 self.wetsuit_time = time + 1;
  1346.                 stuffcmd (self, "bf\n");
  1347.             }
  1348.         }
  1349.  
  1350.         if (self.wetsuit_finished < time)
  1351.         {    // just stopped
  1352. //MED
  1353.          self.items2 = self.items2 - HIP_IT_WETSUIT;
  1354.             self.wetsuit_time = 0;
  1355.             self.wetsuit_finished = 0;
  1356.         }
  1357.     }
  1358.  
  1359. //MED
  1360. // empathy shields
  1361.    if (self.empathy_finished)
  1362.     {
  1363.       // sound and screen flash when items starts to run out
  1364.       if (self.empathy_finished < time + 3)
  1365.         {
  1366.          if (self.empathy_time == 1)
  1367.             {
  1368.             sprint (self, "Empathy Shields are running out\n");
  1369.                 stuffcmd (self, "bf\n");
  1370.                 sound (self, CHAN_AUTO, "items/suit2.wav", 1, ATTN_NORM);
  1371.             self.empathy_time = time + 1;
  1372.             }
  1373.  
  1374.          if (self.empathy_time < time)
  1375.             {
  1376.             self.empathy_time = time + 1;
  1377.                 stuffcmd (self, "bf\n");
  1378.             }
  1379.         }
  1380.  
  1381.       if (self.empathy_finished < time)
  1382.         {    // just stopped
  1383. //MED
  1384.          self.items2 = self.items2 - HIP_IT_EMPATHY_SHIELDS;
  1385.          self.empathy_time = 0;
  1386.          self.empathy_finished = 0;
  1387.         }
  1388. //MED
  1389.       if (self.empathy_finished > time)
  1390.             self.effects = self.effects | EF_DIMLIGHT;
  1391.         else
  1392.             self.effects = self.effects - (self.effects & EF_DIMLIGHT);
  1393.    }
  1394. };
  1395.  
  1396.  
  1397. /*
  1398. ================
  1399. PlayerPostThink
  1400.  
  1401. Called every frame after physics are run
  1402. ================
  1403. */
  1404. void() PlayerPostThink =
  1405. {
  1406.     local    float    mspeed, aspeed;
  1407.     local    float    r;
  1408.  
  1409.     if (self.view_ofs == '0 0 0')
  1410.       {
  1411.       earthquake_postthink();
  1412.       return;     // intermission or finale
  1413.       }
  1414.  
  1415.     //JIM
  1416.     //WETSUIT
  1417.     if (self.wetsuit_finished > time)
  1418.         {
  1419.         if (self.waterlevel==2)
  1420.             {
  1421.             self.velocity = self.velocity * 0.8;
  1422.             }
  1423.         if (self.waterlevel==3)
  1424.             {
  1425.             self.velocity = self.velocity * 0.66;
  1426.             }
  1427.       }
  1428.  
  1429.     //JIM
  1430. //   if (!deathmatch)
  1431. //      {
  1432.       earthquake_postthink();
  1433. //      }
  1434.  
  1435.     if (self.deadflag)
  1436.         return;
  1437.  
  1438. // do weapon stuff
  1439.  
  1440.     W_WeaponFrame ();
  1441.  
  1442. // check to see if player landed and play landing sound
  1443.     if ((self.jump_flag < -300) && (self.flags & FL_ONGROUND) && (self.health > 0))
  1444.     {
  1445.         if (self.watertype == CONTENT_WATER)
  1446.             sound (self, CHAN_BODY, "player/h2ojump.wav", 1, ATTN_NORM);
  1447.         else if (self.jump_flag < -650)
  1448.         {
  1449.             T_Damage (self, world, world, 5);
  1450.             sound (self, CHAN_VOICE, "player/land2.wav", 1, ATTN_NORM);
  1451.             self.deathtype = "falling";
  1452.         }
  1453.         else
  1454.             sound (self, CHAN_VOICE, "player/land.wav", 1, ATTN_NORM);
  1455.  
  1456.         self.jump_flag = 0;
  1457.     }
  1458.  
  1459.     if (!(self.flags & FL_ONGROUND))
  1460.         self.jump_flag = self.velocity_z;
  1461.  
  1462.     CheckPowerups ();
  1463. };
  1464.  
  1465.  
  1466. /*
  1467. ===========
  1468. ClientConnect
  1469.  
  1470. called when a player connects to a server
  1471. ============
  1472. */
  1473. void() ClientConnect =
  1474. {
  1475.     bprint (self.netname);
  1476.     bprint (" entered the game\n");
  1477.  
  1478. // a client connecting during an intermission can cause problems
  1479.     if (intermission_running)
  1480.         ExitIntermission ();
  1481. };
  1482.  
  1483.  
  1484. /*
  1485. ===========
  1486. ClientDisconnect
  1487.  
  1488. called when a player disconnects from a server
  1489. ============
  1490. */
  1491. void() ClientDisconnect =
  1492. {
  1493.     if (gameover)
  1494.         return;
  1495.     // if the level end trigger has been activated, just return
  1496.     // since they aren't *really* leaving
  1497.  
  1498.     // let everyone else know
  1499.     bprint (self.netname);
  1500.     bprint (" left the game with ");
  1501.     bprint (ftos(self.frags));
  1502.     bprint (" frags\n");
  1503.     sound (self, CHAN_BODY, "player/tornoff2.wav", 1, ATTN_NONE);
  1504.     set_suicide_frame ();
  1505. };
  1506.  
  1507. /*
  1508. ===========
  1509. ClientObituary
  1510.  
  1511. called when a player dies
  1512. ============
  1513. */
  1514. void(entity targ, entity attacker) ClientObituary =
  1515. {
  1516.     local    float rnum;
  1517.     local    string deathstring, deathstring2;
  1518.     rnum = random();
  1519.  
  1520.    if (targ.classname == "player")
  1521.     {
  1522.         if (attacker.classname == "teledeath")
  1523.         {
  1524.             bprint (targ.netname);
  1525.             bprint (" was telefragged by ");
  1526.             bprint (attacker.owner.netname);
  1527.             bprint ("\n");
  1528.  
  1529.             attacker.owner.frags = attacker.owner.frags + 1;
  1530.             return;
  1531.         }
  1532.  
  1533.         if (attacker.classname == "teledeath2")
  1534.         {
  1535.             bprint ("Satan's power deflects ");
  1536.             bprint (targ.netname);
  1537.             bprint ("'s telefrag\n");
  1538.  
  1539.             targ.frags = targ.frags - 1;
  1540.             return;
  1541.         }
  1542.  
  1543.         if (attacker.classname == "player")
  1544.         {
  1545.             if (targ == attacker)
  1546.             {
  1547.                 // killed self
  1548.                 attacker.frags = attacker.frags - 1;
  1549.                 bprint (targ.netname);
  1550.  
  1551.                 if (targ.weapon == 64 && targ.waterlevel > 1)
  1552.                 {
  1553.                     bprint (" discharges into the water.\n");
  1554.                     return;
  1555.                 }
  1556.             if (targ.weapon == IT_GRENADE_LAUNCHER)
  1557.                     bprint (" tries to put the pin back in\n");
  1558. //JIM
  1559.             else if (rnum > 0.4 )
  1560.                     bprint (" becomes bored with life\n");
  1561.                 else
  1562.                     bprint (" checks if his weapon is loaded\n");
  1563.                 return;
  1564.             }
  1565.          else if ( (teamplay == 2) && (targ.team > 0)&&(targ.team == attacker.team) )
  1566.             {
  1567.                 if (rnum < 0.25)
  1568.                     deathstring = " mows down a teammate\n";
  1569.                 else if (rnum < 0.50)
  1570.                     deathstring = " checks his glasses\n";
  1571.                 else if (rnum < 0.75)
  1572.                     deathstring = " gets a frag for the other team\n";
  1573.                 else
  1574.                     deathstring = " loses another friend\n";
  1575.                 bprint (attacker.netname);
  1576.                 bprint (deathstring);
  1577.                 attacker.frags = attacker.frags - 1;
  1578.                 return;
  1579.             }
  1580.          else
  1581.             {
  1582.                 attacker.frags = attacker.frags + 1;
  1583. //MED 01/19/97
  1584.             if (empathyused == 1)
  1585.                {
  1586.                bprint (targ.netname);
  1587.                if (random()<0.5)
  1588.                   bprint (" shares ");
  1589.                else
  1590.                   bprint (" feels ");
  1591.                bprint (attacker.netname);
  1592.                bprint ("'s pain\n");
  1593.                return;
  1594.                }
  1595.  
  1596. //MED 11/18/96
  1597.             if (targ.dmg_inflictor.classname == "proximity_grenade")
  1598.                {
  1599.                bprint (targ.netname);
  1600.                if (random()<0.5)
  1601.                   bprint (" got too friendly with ");
  1602.                else
  1603.                   bprint (" did the rhumba with ");
  1604.                bprint (attacker.netname);
  1605.                bprint ("'s bomb\n");
  1606.                return;
  1607.                }
  1608.             rnum = attacker.weapon;
  1609.                 if (rnum == IT_AXE)
  1610.                 {
  1611.                     deathstring = " was ax-murdered by ";
  1612.                     deathstring2 = "\n";
  1613.                 }
  1614. // Grapple
  1615.                     if (rnum == IT_MORNINGSTAR)
  1616.                     {
  1617.                             deathstring = " was disemboweled by ";
  1618.                             deathstring2 = "\n";
  1619.                     }
  1620.                 if (rnum == IT_SHOTGUN)
  1621.                 {
  1622.                     deathstring = " chewed on ";
  1623.                     deathstring2 = "'s boomstick\n";
  1624.                 }
  1625.                 if (rnum == IT_SUPER_SHOTGUN)
  1626.                 {
  1627.                     deathstring = " ate 2 loads of ";
  1628.                     deathstring2 = "'s buckshot\n";
  1629.                 }
  1630.                 if (rnum == IT_NAILGUN)
  1631.                 {
  1632.                     deathstring = " was nailed by ";
  1633.                     deathstring2 = "\n";
  1634.                 }
  1635.                 if (rnum == IT_SUPER_NAILGUN)
  1636.                 {
  1637.                     deathstring = " was punctured by ";
  1638.                     deathstring2 = "\n";
  1639.                 }
  1640.                 if (rnum == IT_GRENADE_LAUNCHER)
  1641.                 {
  1642.                     deathstring = " eats ";
  1643.                     deathstring2 = "'s pineapple\n";
  1644.                     if (targ.health < -40)
  1645.                     {
  1646.                         deathstring = " was gibbed by ";
  1647.                         deathstring2 = "'s grenade\n";
  1648.                     }
  1649.                 }
  1650.                 if (rnum == IT_ROCKET_LAUNCHER)
  1651.                 {
  1652.                     deathstring = " rides ";
  1653.                     deathstring2 = "'s rocket\n";
  1654.                     if (targ.health < -40)
  1655.                     {
  1656.                         deathstring = " was gibbed by ";
  1657.                         deathstring2 = "'s rocket\n" ;
  1658.                     }
  1659.                 }
  1660.                 if (rnum == IT_LIGHTNING)
  1661.                 {
  1662.                     deathstring = " accepts ";
  1663.                     if (attacker.waterlevel > 1)
  1664.                         deathstring2 = "'s discharge\n";
  1665.                     else
  1666.                         deathstring2 = "'s shaft\n";
  1667.                 }
  1668. //MED
  1669.             if (rnum == IT_LASER_CANNON)
  1670.                 {
  1671.                if (random()<0.5)
  1672.                   {
  1673.                   deathstring = " was toasted by ";
  1674.                   }
  1675.                else
  1676.                   {
  1677.                   deathstring = " was radiated by ";
  1678.                   }
  1679.                deathstring2 = "'s laser\n";
  1680.                 }
  1681. //MED
  1682.             if (rnum == IT_MJOLNIR)
  1683.                 {
  1684.                deathstring = " was slammed by ";
  1685.                deathstring2 = "'s hammer\n";
  1686.                 }
  1687.             bprint (targ.netname);
  1688.                 bprint (deathstring);
  1689.                 bprint (attacker.netname);
  1690.                 bprint (deathstring2);
  1691.             }
  1692.             return;
  1693.         }
  1694.         else
  1695.         {
  1696.             targ.frags = targ.frags - 1;        // killed self
  1697.             rnum = targ.watertype;
  1698.  
  1699.             bprint (targ.netname);
  1700.  
  1701. //JIM
  1702.          if ( attacker.deathtype )
  1703.             {
  1704.             bprint( " " );
  1705.             bprint ( attacker.deathtype );
  1706.             bprint( "\n" );
  1707.             return;
  1708.             }
  1709.  
  1710.             if (rnum == -3)
  1711.             {
  1712.                 if (random() < 0.5)
  1713.                     bprint (" sleeps with the fishes\n");
  1714.                 else
  1715.                     bprint (" sucks it down\n");
  1716.                 return;
  1717.             }
  1718.             else if (rnum == -4)
  1719.             {
  1720.                 if (random() < 0.5)
  1721.                     bprint (" gulped a load of slime\n");
  1722.                 else
  1723.                     bprint (" can't exist on slime alone\n");
  1724.                 return;
  1725.             }
  1726.             else if (rnum == -5)
  1727.             {
  1728.                 if (targ.health < -15)
  1729.                 {
  1730.                     bprint (" burst into flames\n");
  1731.                     return;
  1732.                 }
  1733.                 if (random() < 0.5)
  1734.                     bprint (" turned into hot slag\n");
  1735.                 else
  1736.                     bprint (" visits the Volcano God\n");
  1737.                 return;
  1738.             }
  1739.  
  1740.             if (attacker.flags & FL_MONSTER)
  1741.             {
  1742.                 if (attacker.classname == "monster_army")
  1743.                     bprint (" was shot by a Grunt\n");
  1744.                 if (attacker.classname == "monster_demon1")
  1745.                     bprint (" was eviscerated by a Fiend\n");
  1746.                 if (attacker.classname == "monster_dog")
  1747.                     bprint (" was mauled by a Rottweiler\n");
  1748.                 if (attacker.classname == "monster_dragon")
  1749.                     bprint (" was fried by a Dragon\n");
  1750.                 if (attacker.classname == "monster_enforcer")
  1751.                     bprint (" was blasted by an Enforcer\n");
  1752.                 if (attacker.classname == "monster_fish")
  1753.                     bprint (" was fed to the Rotfish\n");
  1754.                 if (attacker.classname == "monster_hell_knight")
  1755.                     bprint (" was slain by a Death Knight\n");
  1756.                 if (attacker.classname == "monster_knight")
  1757.                     bprint (" was slashed by a Knight\n");
  1758.                 if (attacker.classname == "monster_ogre")
  1759.                     bprint (" was destroyed by an Ogre\n");
  1760.                 if (attacker.classname == "monster_oldone")
  1761.                     bprint (" became one with Shub-Niggurath\n");
  1762.                 if (attacker.classname == "monster_shalrath")
  1763.                     bprint (" was exploded by a Vore\n");
  1764.                 if (attacker.classname == "monster_shambler")
  1765.                     bprint (" was smashed by a Shambler\n");
  1766.                 if (attacker.classname == "monster_tarbaby")
  1767.                     bprint (" was slimed by a Spawn\n");
  1768.                 if (attacker.classname == "monster_vomit")
  1769.                     bprint (" was vomited on by a Vomitus\n");
  1770.                 if (attacker.classname == "monster_wizard")
  1771.                     bprint (" was scragged by a Scrag\n");
  1772.                 if (attacker.classname == "monster_zombie")
  1773.                     bprint (" joins the Zombies\n");
  1774. //MED
  1775.             if (attacker.classname == "monster_gremlin")
  1776.                bprint (" was outsmarted by a Gremlin\n");
  1777. //MED
  1778.             if (attacker.classname == "monster_scourge")
  1779.                bprint (" was stung by a Centroid\n");
  1780. //MED
  1781.             if (attacker.classname == "monster_armagon")
  1782.                bprint (" was outgunned by Armagon\n");
  1783.  
  1784.                 return;
  1785.             }
  1786.             if (attacker.classname == "explo_box")
  1787.             {
  1788.                 bprint (" blew up\n");
  1789.                 return;
  1790.             }
  1791.             if (attacker.solid == SOLID_BSP && attacker != world)
  1792.             {
  1793.                 bprint (" was squished\n");
  1794.                 return;
  1795.             }
  1796.             if (targ.deathtype == "falling")
  1797.             {
  1798.                 targ.deathtype = "";
  1799.                 bprint (" fell to his death\n");
  1800.                 return;
  1801.             }
  1802.             if (attacker.classname == "trap_shooter" || attacker.classname == "trap_spikeshooter")
  1803.             {
  1804.                 bprint (" was spiked\n");
  1805.                 return;
  1806.             }
  1807.             if (attacker.classname == "fireball")
  1808.             {
  1809.                 bprint (" ate a lavaball\n");
  1810.                 return;
  1811.             }
  1812.             if (attacker.classname == "trigger_changelevel")
  1813.             {
  1814.                 bprint (" tried to leave\n");
  1815.                 return;
  1816.             }
  1817.  
  1818.          bprint (" died in confusion\n");
  1819.         }
  1820.     }
  1821. };
  1822.